﻿using Microsoft.EntityFrameworkCore;
using PlutoStudio.Dependency;
using PlutoStudio.Domain.UnitOfWork;
using PlutoStudio.EF.Configuration;
using PlutoStudio.Modules;
using System;
using PlutoStudio;
using PlutoStudio.Domain.Services;
using PlutoStudio.Domain.Repositories;
using PlutoStudio.Runtime.Caching.Redis;
using PlutoStudio.Runtime.Caching;
using PlutoStudio.EF;
using PlutoStudio.Events.Bus;
using PlutoStudio.Events.Bus.Entities;
using PlutoStudio.Aspects;
using PlutoStudio.Authorization;
using PlutoStudio.Runtime.Session;
using PlutoStudio.Events.Bus.Handlers;
using PlutoStudio.AutoMapper;
using PlutoStudio.ObjectMapping;
using Castle.Core.Logging;

namespace EntityFrameworkExpample
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var bootstrapper = Bootstrapper.Create<ExpanmpleModule>())
            {
                bootstrapper.UseLog4Net("log4net.config");
                bootstrapper.Initialize();

                var eventbus = bootstrapper.IocManager.Resolve<IEventBus>();
                var logger = bootstrapper.IocManager.Resolve<ILoggerFactory>().Create(typeof(Program));
                eventbus.Register<EntityCreatingEventData<User>>(e =>
                {
                   logger.Info($"Event: EntityCreatingEventData {e.Serialize()}.");
                });
                var service = bootstrapper.IocManager.Resolve<IUserService>();
                service.AddUser(new UserDto { Name = "王五" });
            }
        }


    }

    [AutoMap(typeof(User))]
    public class UserDto
    {
        public string Name { get; set; }
    }

    [Audited]
    class UserService : DomainService, ITransientDependency, IUserService
    {
        private readonly ICacheManager _cacheManager;
        private readonly IRepository<User> _repository;
        private readonly IEventBus _eventBus;
        public UserService(IIocManager iocManager, IRepository<User> repository, ICacheManager cacheManager) 
        {
            _cacheManager = cacheManager;
            _repository = repository;
            _eventBus = iocManager.Resolve<IEventBus>();
        }
        [DisableAuditing]
        public void AddUser(UserDto user)
        {
            var cache = _cacheManager.GetCache("User");
            var id = _repository.InsertAndGetId(ObjectMapper.Map<User>(user));
            cache.Set(id.ToString(), user);
            _eventBus.Trigger(new MyEventData { Name = user.Name });
            Logger.Info($"UserID :{id}");
        }
    }

    class MyEventHandler : IEventHandler<MyEventData>, ITransientDependency
    {
        public ILogger Logger { get; set; }
        public void HandleEvent(MyEventData eventData)
        {
            Logger.InfoFormat("EVENT:MyEventData {0}.", eventData.Serialize());
        }
    }

    class MyEventData : EventData
    {
        public string Name { get; set; }
    }

    [DependsOn(typeof(EntityFrameworkModule))]
    [DependsOn(typeof(RedisCacheModule))]
    [DependsOn(typeof(AutoMapperModule))]
    class ExpanmpleModule : Module
    {

        public override void PreInitialize()
        {
            Configuration.Modules.AutoMapper().UseStaticMapper = true;
            Configuration.Modules.EntityFramework().AddDbContext<DbContext>(c =>
            {
                c.DbContextOptions.UseSqlServer(@"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Test;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=True;ApplicationIntent=ReadWrite;MultiSubnetFailover=False");
            });
            Configuration.Modules.EntityFramework().AddDbContext<DbContext2>(c =>
            {
                c.DbContextOptions.UseSqlServer(@"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Test2;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=True;ApplicationIntent=ReadWrite;MultiSubnetFailover=False");
            });
            base.PreInitialize();
        }
        public override void Initialize()
        {
            IocManager.RegisterAssemblyByConvention(typeof(ExpanmpleModule).Assembly);
            Configuration.Authorization.IsEnabled = true;

            Configuration.Caching.UseRedis(c =>
            {
                c.ConnectionString = "139.196.40.252,password=xstudio,defaultDatabase=9,connectRetry=10, abortConnect=false, allowAdmin=true";
                c.DatabaseId = 0;
            });
            Configuration.Auditing.IsEnabledForAnonymousUsers = true;
            Configuration.Caching.Configure("User", a => { a.DefaultSlidingExpireTime = TimeSpan.FromMinutes(10); });
            base.Initialize();
        }
    }
}
